package com.atguigu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.client.ProductFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.entity.OrderDetail;
import com.atguigu.entity.OrderInfo;
import com.atguigu.enums.OrderStatus;
import com.atguigu.enums.ProcessStatus;
import com.atguigu.mapper.OrderInfoMapper;
import com.atguigu.service.OrderDetailService;
import com.atguigu.service.OrderInfoService;
import com.atguigu.util.HttpClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import springfox.documentation.spring.web.json.Json;

import javax.servlet.http.HttpServletRequest;
import javax.swing.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 订单表 订单表 服务实现类
 * </p>
 *
 * @author zhangqiang
 * @since 2022-08-06
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Value("${cancel.order.delay}")
    private Integer orderDelay;
    @Override
    public Long saveOrderAndDetail(OrderInfo orderInfo) {
        //保存基本信息
        //商品对外交易 outTradeNo
        String outTradeNo="atguigu"+System.currentTimeMillis();
        orderInfo.setOutTradeNo(outTradeNo);  //订单编号
        orderInfo.setTradeBody("买个空调，解暑");
        orderInfo.setCreateTime(new Date());
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        orderInfo.setOrderComment("小单接手");
        //订单过期时间
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE,15);
        orderInfo.setExpireTime(instance.getTime());
        //订单的进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        baseMapper.insert(orderInfo);
        //保存商品信息
        Long orderId = orderInfo.getId();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if(!CollectionUtils.isEmpty(orderDetailList)){
            for (OrderDetail orderDetail : orderDetailList) {
                orderDetail.setOrderId(orderId);
            }
            orderDetailService.saveBatch(orderDetailList);
        }

        //发送一个延迟消息 超时自动取消订单
        rabbitTemplate.convertAndSend(MqConst.CANCEL_ORDER_EXCHANGE,
                MqConst.CANCEL_ORDER_ROUTE_KEY,
                orderId,
                correlationData->{
                    correlationData.getMessageProperties().setDelay(orderDelay);
                    return correlationData;
                });
        return orderId;
    }


    @Override
    public boolean  CompareTradeNo(String tradeNoUi, String userId) {
        String tradeNoKey="user:"+userId+":tradeNo";
        String redisTradeNo = (String)redisTemplate.opsForValue().get(tradeNoKey);
        return tradeNoUi.equals(redisTradeNo);
    }

    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey="user:"+userId+":tradeNo";
        redisTemplate.delete(tradeNoKey);
    }

    @Override
    public String generateTradeNo(String userId) {
        String tradeNo= UUID.randomUUID().toString();
        //在redis中也放一份
        String tradeNoKey="user:"+userId+":tradeNo";
        redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        return tradeNo;
    }

    @Override
    public String checkStockAndPrice(String userId, OrderInfo orderInfo) {
        StringBuilder message = new StringBuilder();
        //拿到用户清单
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //进行验证库存是否充足
        if(!CollectionUtils.isEmpty(orderDetailList))
        for (OrderDetail orderDetail : orderDetailList) {
            Long skuId = orderDetail.getSkuId();
            String skuNum = orderDetail.getSkuNum();
            //b.判断每个商品库存是否足够 访问库存接口
            String url="http://localhost:8100/hasStock?skuId="+skuId+"&num="+skuNum;
            String result = HttpClientUtil.doGet(url);
            if("0".equals(result)){
                message.append("该商品"+orderDetail.getSkuName()+"库存不足,不好意思");
            }
            //判断价格
            BigDecimal realTimePrice = productFeignClient.getSkuPrice(skuId);
            BigDecimal orderPrice = orderDetail.getOrderPrice();
            if(realTimePrice.compareTo(orderPrice)!=0){
                message.append("该商品"+orderDetail.getSkuName()+"价格有变化,请重新刷新页面，重新加入购物车");
            }
        }
        return message.toString();
    }

    @Override
    public OrderInfo checkOrderWithDetail(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        List<OrderDetail> orderDetailList = orderDetailService.list(wrapper);
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    @Override
    public void upOrderStatus(OrderInfo orderInfo, ProcessStatus processStatusName) {
        orderInfo.setOrderStatus(processStatusName.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatusName.name());
        baseMapper.updateById(orderInfo);
    }

    @Override
    public void sendMsgToWareHouse(OrderInfo orderInfo) {
        //a.将订单状态改为已通知仓库
        upOrderStatus(orderInfo,ProcessStatus.NOTIFIED_WARE);
        //b.需要组织一个json类型的数据给仓库系统
        Map<String, Object> houseData = assembleWareHouseData(orderInfo);
        String jsonData= JSON.toJSONString(houseData);
        System.out.println("jsonData:   "+jsonData);
        //c.发消息给仓库系统
        rabbitTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE,MqConst.DECREASE_STOCK_ROUTE_KEY,jsonData);
    }

    @Override
    public String splitOrder(Long orderId, String wareHouseIdSkuIdMapJson) {
        //拿到原始数据
        OrderInfo parentOrderInfoWithDetail = checkOrderWithDetail(orderId);
        //参数格式转换为list [{"wareHouseId":"1","skuIdList":["24","28"]},{"wareHouseId":"2","skuIdList":["25,30,32"]}]
        List<Map> wareHouseIdSkuIdMapList = JSON.parseArray(wareHouseIdSkuIdMapJson, Map.class);
        //多个拼接好的仓库json信息
        List<Object> assembleWareHouseDataList=new ArrayList<>();
        //判断有多少个库遍历
        for (Map wareHouseIdSkuIdMap : wareHouseIdSkuIdMapList) {
            String  wareHouseId = (String) wareHouseIdSkuIdMap.get("wareHouseId");
            List<String> skuIdList = (List<String>) wareHouseIdSkuIdMap.get("skuIdList");
            //2.设置子订单信息
            OrderInfo childOrderInfo = new OrderInfo();
            //完全相同的字段可以复制
            BeanUtils.copyProperties(parentOrderInfoWithDetail,childOrderInfo);
            childOrderInfo.setParentOrderId(orderId);
            childOrderInfo.setId(null);
            //仓库id
            childOrderInfo.setWareHouseId(wareHouseId);
            //购买的商品详情信息
            BigDecimal childTotalMoney = new BigDecimal("0");
            List<OrderDetail> childOrderDetailList=new ArrayList<>();
            List<OrderDetail> parentOrderDetailList = parentOrderInfoWithDetail.getOrderDetailList();
            for (OrderDetail parentOrderDetail : parentOrderDetailList) {
                for (String skuId : skuIdList) {
                    if(Long.parseLong(skuId)==parentOrderDetail.getSkuId()){
                        // skuId= orderDetail,skuId时 说明该 skuId是子订单的商品
                        BigDecimal orderPrice = parentOrderDetail.getOrderPrice();
                        String skuNum = parentOrderDetail.getSkuNum();
                        childTotalMoney=childTotalMoney.add(orderPrice.multiply(new BigDecimal(skuNum)));
                        //基本信息
                        childOrderDetailList.add(parentOrderDetail);
                    }
                }
            }
           childOrderInfo.setOrderDetailList(childOrderDetailList);
           childOrderInfo.setTotalMoney(childTotalMoney);
            //保存子订单及其明细
            //Long userId = childOrderInfo.getUserId();
            saveOrderAndDetail(childOrderInfo);
            //把它弄成订单信息 ---->Map----->Json
            Map<String, Object> wareHouseData = assembleWareHouseData(childOrderInfo);
            //循环里拼接多个 map
            assembleWareHouseDataList.add(wareHouseData);
        }
        //map---->Json
        //4.把原始订单改为split
        upOrderStatus(parentOrderInfoWithDetail,ProcessStatus.SPLIT);
        //5.返回信息给仓库系统
        return JSON.toJSONString(assembleWareHouseDataList);

    }
    //拼接的是一个订单信息
    private Map<String, Object> assembleWareHouseData(OrderInfo orderInfo) {
        //把 orderInfo 格式转为 Map
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("orderId",orderInfo.getId());
        dataMap.put("consignee",orderInfo.getConsignee());
        dataMap.put("consigneeTel",orderInfo.getConsigneeTel());
        dataMap.put("orderComment",orderInfo.getOrderComment());
        dataMap.put("orderBody",orderInfo.getTradeBody());
        dataMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay",2);

        //设置一个仓库id 给仓库拆完单之后返回值使用 无法正常跑
        if(!StringUtils.isEmpty(orderInfo.getWareHouseId())){
            dataMap.put("wareId",orderInfo.getWareHouseId());
        }

        List<Map<String, Object>> orderDetailMapList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            HashMap<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId",orderDetail.getSkuId());
            orderDetailMap.put("skuNum",orderDetail.getSkuNum());
            orderDetailMap.put("skuName",orderDetail.getSkuName());
            orderDetailMapList.add(orderDetailMap);
        }
        dataMap.put("details",orderDetailMapList);
        return dataMap;
    }
}
